/*
 * Preferences.java
 *
 *  created: 3.11.2011
 *  charset: UTF-8
 *  license: MIT (X11) (See LICENSE file for full license)
 */
package cz.mp.k3bg;


import cz.mp.k3bg.log.LoggerManager;
import cz.mp.util.GuiUtils;
import cz.mp.util.StringUtils;
import cz.mp.util.app.ApplicationUtils;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Rectangle;
import java.awt.Window;
import java.util.logging.Logger;
import java.util.prefs.BackingStoreException;

/**
 * Některá nastavení komponent programu, jako jsou velikosti oken.
 * Pro další informace viz {@linkplain java.util.prefs.Preferences}.
 * 
 * @author Martin Pokorný
 * @version 0.1
 * @see java.util.prefs.Preferences
 */
public class Preferences {

    private static final boolean DEBUG = false;
    private static final Logger logger =
            LoggerManager.getLogger(Preferences.class, DEBUG);
    
    // velikost obrazovky
    private static int SCREEN_WIDTH = -1;
    private static int SCREEN_HEIGHT = -1;

    // klíče:
    private static final String WINDOW_X = "x";
    private static final String WINDOW_Y = "y";
    private static final String WINDOW_WIDTH = "width";
    private static final String WINDOW_HEIGHT = "height";    
    private static final String WINDOW_MAXIMIZED = "maximized";
    
    private static final String KINDLEGEN_COMMAND = "kindlegen";
    
    private static final String LAST_RUN_VERSION = "last_run_version";
    
    // -----
    
    /** */
    private Preferences() {        
    }
    
    /**
     * 
     */
    private static void initScreenSize() {
        if (SCREEN_WIDTH <= 0) {
            Dimension screenSize = GuiUtils.getPrimaryScreenSize();
            SCREEN_WIDTH = screenSize.getSize().width;
            SCREEN_HEIGHT = screenSize.getSize().height;
            logger.config("ScreenSize = " 
                    + SCREEN_WIDTH + " x " + SCREEN_HEIGHT);
        }        
    }
    
    /**
     * Zadanému oknu nastaví dříve uloženou velikost nebo ho maximalizuje.
     * 
     * @param window 
     */
    public static void useStoredBounds(Window window) {
        logger.config("window = " + window.getClass().getName());
                
        Rectangle area = getWindowArea(window);
        
        initScreenSize();
        
        int x2 = area.x + area.width;
        int y2 = area.y + area.height;
        
        if (area.width > 0 && area.height > 0 &&
                x2 <= SCREEN_WIDTH && y2 <= SCREEN_HEIGHT) {
            window.setSize(area.width, area.height);
        }
        
        if (area.x > 0 && area.y > 0 &&
                x2 <= SCREEN_WIDTH && y2 <= SCREEN_HEIGHT) {
            window.setLocation(area.x, area.y);
        }
        else {
            logger.fine("center!");
            window.setLocationRelativeTo(null);     // null --> center
        }
        
        if (window instanceof Frame) {
            Frame frame = (Frame) window;
            if (isFrameMaximized(frame)) {
                logger.fine("maximize!");
                GuiUtils.maximize(frame);
            }
        }
    }
    
    /**
     * Získá uloženou pozici a velikost okna.
     * 
     * @param window
     * @return 
     */
    public static Rectangle getWindowArea(Window window) {        
        java.util.prefs.Preferences prefs = getWindowPrefs(window);
        
        int x = prefs.getInt(WINDOW_X, -1);
        int y = prefs.getInt(WINDOW_Y, -1);
        int width = prefs.getInt(WINDOW_WIDTH, -1);
        int height = prefs.getInt(WINDOW_HEIGHT, -1);
        
        return new Rectangle(x, y, width, height);
    }
    
    /**
     * Zjistí zda je okno maximalizováno v uloženém nastavení.
     * 
     * @param frame
     * @return 
     */
    public static boolean isFrameMaximized(Frame frame) {
        java.util.prefs.Preferences prefs = getWindowPrefs(frame);
        
        return prefs.getBoolean(WINDOW_MAXIMIZED, false);
    }
    
    /**
     * 
     * 
     * @param window
     * @param x
     * @param y
     * @param width
     * @param height 
     */
    public static void putWindowArea(Window window, 
            int x, int y, int width, int height) {
        putWindowArea(window, new Rectangle(x, y, width, height));
    }
    
    /**
     * 
     * @param window
     * @param rectangle 
     */
    public static void putWindowArea(Window window, Rectangle rectangle) {
        logger.fine("window = " + window.getClass().getName());
        
        java.util.prefs.Preferences prefs = getWindowPrefs(window);
        
        boolean maximized = false;
        if (window instanceof Frame) {
            Frame frame = (Frame) window;
            maximized = GuiUtils.isMaximized(frame);
            logger.fine("isMaximized = " + maximized);
            prefs.putBoolean(WINDOW_MAXIMIZED, maximized);
        }
        
        if (! maximized) {
            logger.finer("bounds = " + window.getBounds());
            prefs.putInt(WINDOW_X, window.getX());
            prefs.putInt(WINDOW_Y, window.getY());
            prefs.putInt(WINDOW_WIDTH, window.getWidth());
            prefs.putInt(WINDOW_HEIGHT, window.getHeight());
        }
    }
    
    /**
     * Zapomene všechna nastavení okna.
     * 
     * @param window 
     */
    public static void resetWindow(Window window) {
        reset(window.getClass());
    }
    
    /**
     * 
     * 
     * @param clazz
     * @return 
     */
    public static String getKindlegenCmd(Class clazz) {
        java.util.prefs.Preferences prefs = getPrefs(clazz);
        
        return prefs.get(KINDLEGEN_COMMAND, "");
    }
    
    /**
     * 
     * @param clazz
     * @param kindlegenCmd 
     */
    public static void putKindlegenCmd(Class clazz, String kindlegenCmd) {
        logger.fine("kindlegenCmd = " + kindlegenCmd);
        if (StringUtils.isBlank(kindlegenCmd)) {
            throw new IllegalArgumentException("kindlegenCmd is blank");
        }
        java.util.prefs.Preferences prefs = getPrefs(clazz);
        
        prefs.put(KINDLEGEN_COMMAND, kindlegenCmd);
    }
    
    /**
     * Zjistí zda byl tento program spuštěn v jiné verzi než minule.
     * 
     * @param clazz
     * @return 
     */
    public static boolean isVersionChange(Class clazz, String thisVersion) {
        boolean change = false;
        java.util.prefs.Preferences prefs = getPrefs(clazz);
        
        String storedVersion = prefs.get(LAST_RUN_VERSION, "0");
                
        try {
            change = ApplicationUtils
                    .compareVersions(thisVersion, storedVersion) != 0;        
        } catch (NumberFormatException ex) {
            // verze může být i "DEVEL"
            return !DEBUG;
        }
        
        return change;
    }
    
    /**
     * 
     * @param clazz
     * @return 
     */
    public static String getLastRunVersion(Class clazz) {
        java.util.prefs.Preferences prefs = getPrefs(clazz);        
        return prefs.get(LAST_RUN_VERSION, "0");
    }
    
    /**
     * 
     * @param clazz
     * @param version 
     */
    public static void putLastRunVersion(Class clazz, String version) {
        logger.fine("version = " + version);
        if (StringUtils.isBlank(version)) {
            throw new IllegalArgumentException("version is blank");
        }
        java.util.prefs.Preferences prefs = getPrefs(clazz);
        
        prefs.put(LAST_RUN_VERSION, version);
    }
    
    /**
     * Zapomene všechna nastavení třídy.
     * 
     * @param clazz 
     */
    public static void reset(Class clazz) {
        java.util.prefs.Preferences prefs = getPrefs(clazz);
        
        try {
            prefs.clear();
        } catch (BackingStoreException ex) {
            logger.warning(ex.toString());
        }
    }
    
    /**
     * 
     * @param window
     * @return 
     */
    private static java.util.prefs.Preferences getWindowPrefs(Window window) {
        return getPrefs(window.getClass());
    }
    
    /**
     * 
     * @param clazz
     * @return 
     */
    private static java.util.prefs.Preferences getPrefs(Class clazz) {
        java.util.prefs.Preferences prefs = java.util.prefs.Preferences.userRoot();
        prefs = prefs.node(Application.NAME + "/" + clazz.getName());
        return prefs;
    }    

}   // Preferences.java

